package jsonpb

import (
	"bytes"
	"sync"

	"github.com/golang/protobuf/jsonpb"
	"github.com/golang/protobuf/proto"
)

var marshaller = &jsonpb.Marshaler{EmitDefaults: true, OrigName: true, EnumsAsInts: true}

func Marshal(pb proto.Message) (string, error) {
	e := newEncodeState()
	if err := marshaller.Marshal(e, pb); err != nil {
		return "", err
	}

	s := e.String()
	e.Reset()
	encodeStatePool.Put(e)

	return s, nil
}

func MarshalBytes(pb proto.Message) ([]byte, error) {
	e := newEncodeState()
	if err := marshaller.Marshal(e, pb); err != nil {
		return nil, err
	}

	buf := append([]byte(nil), e.Bytes()...)
	e.Reset()
	encodeStatePool.Put(e)
	return buf, nil
}

// An encodeState encodes proto into a bytes.Buffer.
type encodeState struct {
	*bytes.Buffer
}

var encodeStatePool sync.Pool

func newEncodeState() *encodeState {
	if v := encodeStatePool.Get(); v != nil {
		e := v.(*encodeState)
		e.Reset()
		return e
	}
	return &encodeState{Buffer: bytes.NewBuffer(make([]byte, 0, 2048))}
}
